package it.tukano.treditor.modules;

import it.tukano.app.AbstractAppModule;
import it.tukano.app.AppModule;
import it.tukano.check.Todo;
import it.tukano.io.FileExt;
import it.tukano.io.FileExt.InputStreamCall;
import it.tukano.io.FileExt.OutputStreamCall;
import it.tukano.reflection.MethodExt;
import it.tukano.swingdeco.filechooser.ExtensionFileFilter;
import it.tukano.swingdeco.filechooser.JFileChooserExt;
import it.tukano.swingdeco.menubar.JMenuExt;
import it.tukano.treditor.engine.scene.NodeElement;
import it.tukano.treditor.resources.Configuration;
import it.tukano.treditor.resources.Configuration.ConfigurationKey;
import it.tukano.treditor.resources.Labels;
import it.tukano.treditor.resources.Labels.LabelKey;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * Read/write stored files
 * @author pgi
 */
public class IOModule extends AbstractAppModule {
    
    private FileExt currentTreditorFile = null;
    private Labels labels = Labels.getInstance();
    private JMenuExt ioMenu = new JMenuExt(labels.getLabelValue(LabelKey.FILE)).addButtons(
            labels.getLabelValue(LabelKey.NEW),
            labels.getLabelValue(LabelKey.OPEN),
            labels.getLabelValue(LabelKey.SAVE),
            labels.getLabelValue(LabelKey.SAVE_AS),
            labels.getLabelValue(LabelKey.EXPORT))
            .onActionPerformed(new MethodExt(this, "ioMenuActionPerformed", ActionEvent.class));
    private final JFileChooserExt treditorFileChooser = new JFileChooserExt().withFilter(new ExtensionFileFilter(
            Labels.getInstance().getLabelValue(LabelKey.TREDITOR_FILE_DESCRIPTION),
            Configuration.getInstance().get(ConfigurationKey.TREDITOR_FILE_EXTENSION)));

    /**
     * Instance initializer
     */
    public IOModule() {
    }

    @Override
    public void startModule(AppModule context) {
        final MainFrame mainFrame = find(MainFrame.class);
        mainFrame.installMenuComponent(ioMenu);
    }
    
    public void ioMenuActionPerformed(ActionEvent e) {
        final LabelKey key = labels.getLabelKey(e.getActionCommand());
        switch(key) {
            case NEW:
                createNewScene();
                break;
            case OPEN:
                openTreditorFile();
                break;
            case SAVE:
                saveTreditorFile();
                break;
            case SAVE_AS:
                saveTreditorFileAs();
                break;
            case EXPORT:
                exportScene();
                break;
            default:
                Todo.implementThis();
        }
    }

    public void createNewScene() {
        find(MainFrame.class).popupYesNoDialog(labels.getLabelValue(LabelKey.NEW_SCENE_CONFIRM), new Runnable() {

            public void run() {
                NodeElement root = new NodeElement();
                root.setName(labels.getLabelValue(LabelKey.DEFAULT_SCENE_ROOT_NAME));
                find(DataModel.class).setSceneRoot(this, root);
            }
        });
    }

    public void openTreditorFile() {
        find(MainFrame.class).popupYesNoDialog(labels.getLabelValue(LabelKey.NEW_SCENE_CONFIRM), new Runnable() {

            public void run() {
                confirmedOpenTreditorFile();
            }
        });
    }
    
    protected void confirmedOpenTreditorFile() {
        final MainFrame mainFrame = find(MainFrame.class);
        final Component component = mainFrame.getModalDialogsParent();
        if(currentTreditorFile != null) {
            treditorFileChooser.setCurrentDirectory(currentTreditorFile.getParent().getFile());
        }
        FileExt chosenFile = treditorFileChooser.showCheckedOpenDialog(component, getTreditorFileExtensions());
        if(chosenFile != null) {
            currentTreditorFile = chosenFile;
            String error = chosenFile.withInputStream(new InputStreamCall<String>() {

                public String call(InputStream in) throws Throwable {
                    return find(TreditorFileReader.class).doLoadTreditorFile(in);
                }
            });
            if(error != null) {
                Todo.implementThis("change to warning dialog");
                find(MainFrame.class).popupMessageDialog(error);
            }
        }
    }
    
    protected String doSaveTreditorFile(OutputStream out) throws Throwable {
        return find(TreditorFileWriter.class).doSaveTreditorFile(out);
    }
    
    protected String[] getTreditorFileExtensions() {
        return new String[] {Configuration.getInstance().get(Configuration.ConfigurationKey.TREDITOR_FILE_EXTENSION) };
    }

    public void saveTreditorFile() {
        final MainFrame mainFrame = find(MainFrame.class);
        final Component component = mainFrame.getModalDialogsParent();
        if(currentTreditorFile != null) treditorFileChooser.setSelectedFile(currentTreditorFile.getFile());
        final FileExt confirmedFile = treditorFileChooser.showCheckedSaveDialog(component, getTreditorFileExtensions());
        if(confirmedFile != null) {
            currentTreditorFile = confirmedFile;
            saveCurrentTreditorScene(currentTreditorFile);
        }
    }

    public void saveTreditorFileAs() {
        Todo.implementThis();
    }

    public void exportScene() {
        Todo.implementThis();
    }

    private void saveCurrentTreditorScene(FileExt file) {
        String error = file.withOutputStream(new OutputStreamCall<String>() {

            public String call(OutputStream out) throws Throwable {
                return doSaveTreditorFile(out);
            }
        });
        final MainFrame mainFrame = find(MainFrame.class);
        if(error == null) {
            mainFrame.popupMessageDialog(Labels.getInstance().getLabelValue(LabelKey.TREDITOR_FILE_WRITTEN));
        } else {
            Todo.implementThis("change to warning dialog");
            mainFrame.popupMessageDialog(Labels.getInstance().getLabelValue(LabelKey.TREDITOR_FILE_WRITE_FAILURE));
        }
    }
}